#ifndef __HomeTether_Common_h__
#define __HomeTether_Common_h__

#if defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_SD)
#  define _STM32F10X
#endif


#ifdef _STM32F10X
#include "stm32f10x.h"
#include "stm32f10x_flash.h"
// #include "../../common/core_cm3.h"

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>

/*
#ifndef TRUE
#  define FALSE (0)
#  define TRUE  (1)
#  define BOOL  uint8_t
#endif // TRUE 
*/

#ifndef BOOL
#  define BOOL  uint8_t
#endif // BOOL

#ifndef max 
#  define max(_A, _B) ((_A>_B)?_A:_B)
#endif
#ifndef min 
#  define min(_A, _B) ((_A<_B)?_A:_B)
#endif

#define BYTES2WORD( _BYTE_HIGH, _BYTE_LOW) ((((uint16_t)_BYTE_HIGH) <<8) | (_BYTE_LOW &0xff))

#ifdef _STM32F10X
typedef struct IO_PIN
{
	GPIO_TypeDef* port;
	uint16_t      pin;	
} IO_PIN;

#define pinH(_IoPin) GPIO_SetBits(_IoPin.port, _IoPin.pin)
#define pinL(_IoPin) GPIO_ResetBits(_IoPin.port, _IoPin.pin)
#endif // _STM32F10X

#define SystemFrequency (72000)	  //TODO need to correct


#if 0
// -----------------------------
// memory
// -----------------------------
void memset(void *dest, char c, uint32_t len);
int  memcpy(void *dest, void *src, unsigned int len);
int  memcmp(void *dst, void *src, unsigned int len);

// -----------------------------
// string & character
// -----------------------------
int  strlen(const char *s);
void strcpy(char *s1, const char *s2);
int  strcmp(const char *s1, const char *s2);
char* strcat(char *s1, const char *s2);
long atol(char *str);
char* strstr(const char* src, const char* dst);  
#endif // 0

char* trimleft(const char *s);
char* strchar(const char *s, char c);	 // ???????

unsigned char ltoa(unsigned int val, char *buffer);

#endif // _STM32F10X

char hexchar(const unsigned char n);
uint8_t hexchval(char ch);
const char* hex2int(const char* hexstr, uint32_t* pVal);


/*
char *str_char(char *s, char c);
int is_ascii(char c);
void get_quotient(unsigned int dividend, unsigned int divisor, char * buf, unsigned char num);
unsigned char calculate_xor_val(unsigned char * addr, unsigned int len);
*/
// -----------------------------
// debug
// -----------------------------
#define DEBUG
#ifdef DEBUG
extern uint8_t log_level;

#pragma __printf_args
void log(uint8_t level, const char * __restrict /*format*/, ...);
#endif // DEBUG

// -----------------------------
// delay
// -----------------------------
void delayXusec(int32_t usec);
void delayXmsec(int32_t msec);

// -----------------------------
// processing about message line that ends with \r or \n
// \0 will be taken as a intermedia terminator of one transmision
// -----------------------------
#ifndef MAX_MSGLEN
#define MAX_MSGLEN     80
#endif

#ifndef MAX_PENDMSGS
#define MAX_PENDMSGS   (2)
#endif

typedef struct _MsgLine
{
	uint8_t chId, offset, timeout;
	char msg[MAX_MSGLEN];
} MsgLine;

extern volatile MsgLine _pendingLines[MAX_PENDMSGS]; //  = { {} };
void MsgLine_init(void);
volatile MsgLine* MsgLine_allocate(uint8_t chId, uint8_t reservedTimeout);
void MsgLine_free(volatile MsgLine* pLine);
int  MsgLine_recv(uint8_t pipeId, uint8_t* inBuf, uint8_t maxLen);
void MsgLine_log(uint8_t ifChId, char * fmt, ...);

// -----------------------------
// BlinkTick
// -----------------------------
// about blink an output
typedef struct _BlinkTick
{
	uint8_t tick, reloadOn, reloadOff;
} BlinkTick;

bool Blink_isActive(BlinkTick* pPT);
bool Blink_tick(BlinkTick* pBT);
void Blink_config(BlinkTick* pPT, uint8_t reloadOn, uint8_t reloadOff);
void Blink_configByUri(BlinkTick* pPT, char* msg);

// -----------------------------
// timer array
// -----------------------------
// Usage:
//    1) call Timer_init(void) to initialiaze TIMER_MAX_NUM timers, and call the bsp func to setup the timer every 1msec
//    2) make the 1msec interrupt ISR_OnTick() to call Timer_scan(), that latter will decrease the counter of each live timer
//    3) make your loop to call Timer_exec(), the latter will check if the counter of any timer has been reached, execute it if so
//    4) call Timer_start() with timervalue and callback to employ a timer to wake up the callback in the given msec
//    5) call Timer_stop() to disable an active timer
#define TIMER_MAX_NUM          		3
typedef void (*func_OnTimer)(void* pCtx);

void Timer_init(void);
void Timer_start(uint8_t n, uint32_t msec, func_OnTimer func, void* pCtx);
void Timer_stop(uint8_t n);

void Timer_OnTick(void);
void Timer_scan(void);
uint32_t Timer_isStepping(uint8_t n);

#endif // __HomeTether_Common_h__
